package com.culture.config.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javax.annotation.Resource;

import com.culture.config.common.util.BeanUtil;
import com.culture.config.common.util.ExceptionUtil;
import com.culture.config.dao.entity.Menu;
import com.culture.config.dao.mapper.MenuMapper;
import com.culture.config.service.MenuService;
import com.culture.config.model.po.*;
import com.culture.config.model.vo.*;
import com.culture.config.wrapper.MenuWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;

import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class MenuServiceImpl implements MenuService{
    @Resource
    private MenuMapper menuMapper;

    @Override
    public Page<MenuVO> page(MenuPageParam param) {     
        PageMethod.startPage(param.getPageNum(),param.getPageSize());
		Page<Menu> menuList = this.menuMapper.pageByParent(MenuWrapper.wrapMenuQuery(param));      
		return BeanUtil.copyPageProperties(menuList, MenuVO.class);
    }

    @Override
    public void add(MenuAddPO menuAddPO) {
        log.info("add menu:{}",menuAddPO);
        this.menuMapper.add(MenuWrapper.wrapMenuAdd(menuAddPO));
    }

    @Override
    public void update(MenuUpdatePO menuUpdatePO) {
        log.info("update menu:{}",menuUpdatePO);
        this.menuMapper.update(MenuWrapper.wrapMenuUpdate(menuUpdatePO));
    }

    @Override
    public List<MenuVO> list(MenuSearchPO param) {
        List<Menu> menuList = this.menuMapper.listByName(MenuWrapper.wrapMenuSearch(param));      
		return BeanUtil.copyListProperties(menuList, MenuVO.class);
    }

    @Override
    public MenuTreeVO tree(MenuTreePO menuTreePO) {
        List<Menu> menuList = this.menuMapper.listAll(); 
        return MenuWrapper.wrapMenuTreeVO(menuList);
    }

    @Override
    public void move(MenuMovePO menuMovePO) {
        log.info("Move menu:{}",menuMovePO);
        ExceptionUtil.businessExceptionWhenTrue(menuMovePO.getId().equals(menuMovePO.getParentId()), "Can't move to self"); 
        Menu menu = this.menuMapper.get(new Menu(menuMovePO.getId()));  
        ExceptionUtil.businessExceptionWhenNull(menu, "Menu not found");
        if(menu.getParentId().equals(menuMovePO.getParentId())){
            return;
        }
        if(menuMovePO.getParentId() > 0){
            Menu targetMenu = this.menuMapper.get(new Menu(menuMovePO.getParentId()));
            ExceptionUtil.businessExceptionWhenNull(targetMenu, "Not found target menu");
            ExceptionUtil.businessExceptionWhenTrue(targetMenu.getIsLeaf().equals(1), "Target menu is leaf");
            List<Menu> childList = Optional.ofNullable(this.menuMapper.listByParentId(new Menu().setParentId(menuMovePO.getId()))).orElse(Collections.emptyList());
            childList.forEach(m->this.checkValidateParent(m.getId(),targetMenu.getId(),0));
        }       
        this.menuMapper.update(MenuWrapper.wrapMenuMove(menuMovePO));
    }

    private void checkValidateParent(Long childId, Long parentId, Integer level){
        log.info("checkValidateParent:{},{}",childId, parentId);
        ExceptionUtil.businessExceptionWhenTrue(childId.equals(parentId), "Target menu error");  
        ExceptionUtil.businessExceptionWhenTrue(level.equals(10), "Menu data level error");  
        List<Menu> childList = Optional.ofNullable(this.menuMapper.listByParentId(new Menu().setParentId(childId))).orElse(Collections.emptyList());
        childList.forEach(m->this.checkValidateParent(m.getId(), parentId, level + 1));
    }
}
